package com.bwie.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsProd;
import com.bwie.mapper.TbProdAttaMapper;
import com.bwie.pojo.TbProd;
import com.bwie.pojo.TbProdAtta;
import com.bwie.service.TbProdService;
import com.bwie.mapper.TbProdMapper;
import com.bwie.utils.R;
import com.bwie.utils.TokenUtils;
import com.bwie.vo.PageInfoVo;
import com.bwie.vo.ProdPageVo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
* @author Lenovo
* @description 针对表【tb_prod(商品表)】的数据库操作Service实现
* @createDate 2025-06-20 15:28:36
*/
@Service
public class TbProdServiceImpl extends ServiceImpl<TbProdMapper, TbProd>
    implements TbProdService{

    @Autowired
    TbProdMapper tbProdMapper;
    @Autowired
    HttpServletRequest request;
    @Autowired
    TbProdAttaMapper tbProdAttaMapper;
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public R getProdList(ProdPageVo prodPageVo) {
        Page<TbProd> page = new Page<>(prodPageVo.getPageNum(), prodPageVo.getPageSize());

        Page<TbProd> tbProdPage = tbProdMapper.getProdList(page,prodPageVo);
        return R.ok(tbProdPage);
    }

    @Override
    public R addProd(TbProd tbProd) {
        TbProd prod = tbProdMapper.selectOne(
                new LambdaQueryWrapper<TbProd>()
                        .eq(TbProd::getProdName, tbProd.getProdName())
                        .or()
                        .eq(TbProd::getProdName,tbProd.getProdName())
        );
        if(prod != null){
            return R.error(500,"该商品已经存在");
        }

        String spu = RandomUtil.randomNumbers(4);
        tbProd.setProdSpu(spu);

        String token = request.getHeader("token");
        String userName = TokenUtils.getUserName(token);
        tbProd.setCreateBy(userName);
        tbProd.setCreateTime(new Date());

        tbProdMapper.insert(tbProd);

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R addProdAtta(TbProdAtta tbProdAtta) {
        //判断商品是否存在
        TbProd tbProd = tbProdMapper.selectById(tbProdAtta.getProdId());
        if(tbProd == null){
            return R.error(404,"商品不存在");
        }
        //删除原有附件,根据商品ID进行删除
        tbProdAttaMapper.delete(
                new LambdaQueryWrapper<TbProdAtta>().eq(TbProdAtta::getProdId,tbProdAtta.getProdId())
        );

        //添加附件
        String token = request.getHeader("token");
        String userName = TokenUtils.getUserName(token);
        tbProdAtta.setCreateBy(userName);
        tbProdAtta.setCreateTime(new Date());
        tbProdAttaMapper.insert(tbProdAtta);

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteBatchProd(List<Integer> ids) {
        if(ids == null || ids.size()<=0){
            return R.error(404,"请选择要删除的数据");
        }
        //批量删除商品
        tbProdMapper.deleteBatchIds(ids);
        //批量删除商品附件
        tbProdAttaMapper.delete(
                new LambdaQueryWrapper<TbProdAtta>().in(TbProdAtta::getProdId,ids)
        );

        return R.ok();
    }

    @Override
    public R deleteProd(Integer id) {
        TbProd tbProd = tbProdMapper.selectById(id);
        if(tbProd == null){
            return R.error(404,"商品不存在");
        }

        tbProdMapper.deleteById(id);
        return R.ok();
    }

    @Override
    public R getProdFromEs(ProdPageVo prodPageVo) {
        Integer pageNum = 0;
        if(prodPageVo.getPageNum()>0){
            pageNum = prodPageVo.getPageNum() - 1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, prodPageVo.getPageSize());

        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        if(StringUtils.isNotEmpty(prodPageVo.getKeyWord())){
            boolQueryBuilder.should(QueryBuilders.matchQuery("prodName",prodPageVo.getKeyWord()))
                    .should(QueryBuilders.matchQuery("brandName",prodPageVo.getKeyWord()))
                    .should(QueryBuilders.matchQuery("prodId",prodPageVo.getKeyWord()));
        }

        if(ObjectUtils.isNotEmpty(prodPageVo.getStatusId())){
            boolQueryBuilder.must(QueryBuilders.termQuery("prodStatus",prodPageVo.getStatusId()));
        }

        if(StringUtils.isNotEmpty(prodPageVo.getBeginTime()) && StringUtils.isNotEmpty(prodPageVo.getEndTime()) ){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime")
                    .format("yyyy-MM-dd HH:mm:ss")
                    .timeZone("GMT+8")
                    .from(prodPageVo.getBeginTime())
                    .to(prodPageVo.getEndTime()));
        }

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("prodName").field("brandName").preTags("<font color='red'>").postTags("</font>");

        //排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("prodId").order(SortOrder.DESC);

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withPageable(pageRequest)
                .withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withSort(sortBuilder);

        SearchHits<EsProd> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsProd.class);

        long total = searchHits.getTotalHits();
        ArrayList<EsProd> records = new ArrayList<>();

        for (SearchHit<EsProd> searchHit : searchHits.getSearchHits()) {

            EsProd esProd = searchHit.getContent();

            List<String> prodName = searchHit.getHighlightField("prodName");
            if(prodName != null && prodName.size()>0){
                esProd.setProdName(prodName.get(0));
            }

            List<String> brandName = searchHit.getHighlightField("brandName");
            if(brandName != null && brandName.size()>0){
                esProd.setBrandName(brandName.get(0));
            }

            records.add(esProd);
        }

        HashMap<String, Object> map = new HashMap<>();
        map.put("total",total);
        map.put("records",records);
        return R.ok(map);
    }
}




